Bag om supersøgeren Lucene

Lucene er en Java-baseret tekstsøgemaskine, som kan håndtere ganske store tekstmængder. Den indekserer i en rivende fart og indeholder masser af finurlig funktionalitet. I en tidligere artikel har vi set på, hvorledes Lucene kan anvendes i et konkret eksempel. Her ser vi på Java-koden bag eksemplet, og det er faktisk forbavsende simpelt.

50 millioner websider

Lucene er en Java-baseret maskine til indeksering og søgning i tekst. I forrige artikel om søgemaskinen viste vi, at selv på et gammelt hakkebræt af en computer klarer Lucene uden problemer fritekstsøgning gennem 500 megabyte data med øjeblikkelige svartider.

Lucene er ikke en database. Den holder ikke på data, men indekserer kun tekster, som må gemme sig andre steder. Det kan oplagt være i en database, men det kan også blot være flade filer på et drev.

Lucene er skrevet i Java, og er open source under samme licens som webserveren Apache, hvilket vil sige, at den kan anvendes også i kommercielle sammenhænge.

Hovedmanden bag Lucene er Doug Cutting, som har mange års erfaring indenfor teori og praksis angående søgemaskiner. Han står blandt andet bag websitet Excites søgning på indholdet på 50 millioner websider og en søgeteknologi, som er indbygget i Apples Macintosh-styresystem.

Første udgave af Lucene blev skrevet i 1998, og kildekoden blev udgivet under open source-licens i 2000.

Vi skal ikke gå i detaljer om virkemåden i Lucene, for det er en temmelig langhåret sag. Lucene benytter optimeringer af flere kendte metodikker i forbindelse med tekstsøgning, og det gør den ganske fint. En artikel i vort amerikanske søsterorgan JavaWorld beskriver virkemåden bag den effektive indeksering.

Men her ser vi nærmere på, hvorledes Lucene kan benyttes i egne applikationer.

Lucene er oplagt til brug i serversystemer, hvor de indekserede tekster kan være offentligt tilgængelige, eller blot fælles ressourcer, som for eksempel på et internt netværk eller intranet. Lucene kan downloades som Web-applikation (.war-fil), der kan benyttes med Tomcat eller andre Servlet-containere.

Men som i vores eksempel kan Lucene også anvendes til klient-systemer og helt almindelige Java-programmer.

Lucene indekserer kun, og berører ikke de indekserede tekster på anden vis. Derfor kan Lucene indeksere alle slags formater, bare teksten kan udtrækkes. Lucene kan altså også anvendes til formater som PDF og Word, bare man har en måde at udtrække teksten af formatet, og den slags filtre findes der mange af.

Teksten indekseres

Teksten indekseres
Lucene benyttes ved at downloade en jar-fil og tilføje den til classpath'en. Lucenes http://jakarta.apache.org/lucene/docs/api/" TARGET="_blank">API er veldokumenteret, og ganske nemt at følge. Der er mange måder at anvende Lucene på, og den vi skitserer her, berører kun en lille del af de mange muligheder.

Det objekt, som indekserer teksten og skriver de indekser, som Lucene benytter under søgningen, hedder IndexWriter. De genererede indekser kan gemmes på harddisken, i hukommelsen, i en database eller hvor man nu synes, at man vil gemme dem. Det nemmeste er blot at gemme dem på harddisken, så det gør vi her.

java.io.File indexes = new java.io.File("indexes");
writer = new IndexWriter(indexes, new SimpleAnalyzer(), true);

Før vi koder løs, opretter vi en mappe (directory) på harddisken, som vi døber "indexes". Så skaber vi en ny instans af IndexWriter, og constructoren giver vi tre argumenter. Første argument er mappen "indexes", som IndexWriter skal gemmes indekserne i. Det næste argument i constructoren er en instans af et Analyzer-objekt, og det skal forklares.

Lucene indekserer ikke alle ord ukritisk, men benytter en instans af et Analyzer-objekt til at filtrere eksempelvis ofte forekommende ord fra teksten, som ellers ville belaste indekserne unødigt og dermed give dårligere ydelse.

Derfor skal man benytte en Analyzer. Man kan skrive sin egen Analyzer, eller benytte en af de tre som medfølger i Lucene: SimpleAnalyzer, StandardAnalyzer og GermanAnalyzer. SimpleAnalyzer benyttes til engelsk, GermanAnalyzer til tysk, og ved hjælp af StandardAnalyzer og udvidelsen Snowball kan man benytte en lang række andre sprog, herunder dansk.

I vort eksempel fra forrige artikel var det encyklopædien Wikipedia, som er på engelsk, som vi ville indeksere, så derfor benytter vi en instans af SimpleAnalyzer.

Det sidste argument til IndexWriter er konstanten true, som angiver, at vi ønsker at skabe et nyt indeks i stedet for at anvende et allerede eksisterende.

Nu kan indekset fyldes med dokumenter. Det gøres ved hjælp af IndexWriters metode addDocument, og det, som skal lægges til, er et Lucene Document-objekt. Et dokument består af en række Field-instanser, som tilføjer tekst, der enten kan indekseres, eller blot gemmes i tilknytning til dokumentet. Det kan for eksempel være et filnavn, som senere kan identificere kilden.

Document document = new Document();

document.add(Field.UnIndexed("filename", filename));
document.add(Field.Text("title", title));
document.add(Field.Text("article", articleText));

writer.addDocument(document);

Som det ses, tilføjes Field-instanser ved hjælp af statiske metoder, som i

Field.UnIndexed("filename", filename)

Det første argument i metoden er feltnavnet, som blot er en streng ("filename"), der identificerer feltet. Dernæst er det så feltets indhold, som også er en streng. Denne metode genererer et felt, som ikke skal indekseres.

De tekster, som vi gerne vil indeksere, tilføjer vi dokumentet ved hjælp af metoden

Field.Text("title", title)

Ligesom før angiver første argument et feltnavn, mens næste argument, title, er teksten, som skal indekseres.

Til sidst tilføjes document-instansen til IndexWriter-instansen med linjen

writer.addDocument(document);

- og mere er der faktisk ikke i det - ud over at gennemløbe samtlige dokumenter på denne facon.

Som sagt er der masser af fleksibilitet i Lucenes indekseringsmuligheder, og i slutningen af denne artikel giver vi en række henvisninger til videre læsning.

Søgning

Søgning
Lucene indeholder en lang række søgemuligheder, inklusive sit eget søgesprog, mulighed for såkaldt fuzzy search, og mere til. Her kradser vi kun lige i lakken, men en af de rare ting ved Lucene er, at API'et er veldokumenteret og nemt at forstå.

Lad os forestille at vi vil gennemsøge artiklerne i vores encyklopædi-eksempel med søgestrengen "Napoleon". Det kunne se sådan ud:

String queryString = "Napoleon";
File indexes = new File(indexes");
Searcher searcher = new IndexSearcher(indexes.getAbsolutePath());
Query query =
  QueryParser.parse(queryString, "article", new SimpleAnalyzer());
Hits hits = searcher.search(query);
for (int i = 0; i < hits.length(); i++) {
  System.out.println(
  hits.doc(i).get("filename") + " score: " + hits.score(i));
}

Her gennemsøger vi vores tidligere skabte indeks med strengen "Napoleon". Det gøres med Lucene-objektet IndexSearcher, hvis constructor kaldes med stien til vores indeks som argument.

Dernæst skal vi bruge en instans af Lucenes Query-objekt. Query-instansen skabes ved hjælp af en statisk metode i objektet QueryParser:

Query query =
  QueryParser.parse(queryString, "article", new SimpleAnalyzer());

De tre argumenter er strengen vi leder efter, det felt i dokumenterne, hvor vi leder efter strengen (feltet "article"), og til sidst den Analyzer, som benyttedes ved indekseringen.

Søgningen udføres ved sætningen

Hits hits = searcher.search(query);

som populerer Hits-objektets instans med de dokumenter, som blev fundet ved søgningen.
Til sidst udskriver vi de fundne dokumenters filnavn, og hittets score, hvilket er dokumentets relevans.

Filnavnet gemte vi tidligere i et felt, som vi gav navnet "filename". Dette felt, og tilsvarende alle mulige andre felter som er tilknyttet det fundne dokument, kan hentes frem ved hjælp af linjen

hits.doc(i).get("filename")

Relevansen, hittets score, hentes med

hits.score(i)

Videre læsning
Den tidligere nævnte artikel fra JavaWorld giver en god introduktion til Lucene, og en anden udmærket online-artikel findes i tidsskriftet Java Developer's Journals arkiver.




Brancheguiden
Brancheguide logo
Opdateres dagligt:
Den største og
mest komplette
oversigt
over danske
it-virksomheder
Hvad kan de? Hvor store er de? Hvor bor de?
Fiftytwo A/S
Konsulentydelser og branchespecifikke softwareløsninger til retail, e-Commerce, leasing og mediebranchen.

Nøgletal og mere info om virksomheden
Skal din virksomhed med i Guiden? Klik her

Kommende events
Send dine legacysystemer på pension og invitér standardløsninger indenfor

Legacysystemer er rygraden i mange organisationers it-infrastruktur, men før eller siden er det tid til at sige farvel og skifte til en eller flere standardløsninger. Vi udforsker scenarier og muligheder, der gør det muligt at rykke videre. Hvad er businesscasen? Hvilke krav stiller skiftet til din forretning og jeres processer? Hvordan

08. oktober 2024 | Læs mere


Dynamics 365 & Business Central - AI og branchemoduler

Udforsk, hvordan du kommer godt i gang med Business Central, får hjælp til at tilpasse platformen til dine behov og får mest ud af din ERP-løsning med begrænsede ressourcer.

23. oktober 2024 | Læs mere


Årets CISO 2024

Vær med når Computerworld, Dansk Erhverv og Rådet for Digital Sikkerhed tager temperaturen på trusselslandskabet lige nu, og giver dig overblikket over de nyeste trusler, de mest aktuelle tendenser og de bedste løsninger og værktøjer til at sikre effektiv drift og høj compliance.

24. oktober 2024 | Læs mere